package org.zpmis.api.business;

import cn.hutool.core.lang.UUID;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zpmis.common.base.AdminLoginUser;
import org.zpmis.common.base.BaseWebService;
import org.zpmis.common.constant.UserConstants;
import org.zpmis.common.exception.BusinessException;
import org.zpmis.common.result.ResultCode;
import org.zpmis.common.utils.StringUtil;
import org.zpmis.domain.role.model.SysMenu;
import org.zpmis.domain.role.model.SysPermission;
import org.zpmis.domain.role.model.SysRoleMenuRelation;
import org.zpmis.domain.role.model.SysRolePermissionRelation;
import org.zpmis.domain.role.qo.AddSysMenuQo;
import org.zpmis.domain.role.qo.DelSysMenuQo;
import org.zpmis.domain.role.qo.EditSysMenuQo;
import org.zpmis.domain.role.qo.SysMenuListQo;
import org.zpmis.domain.role.service.SysMenuService;
import org.zpmis.domain.role.service.SysPermissionService;
import org.zpmis.domain.role.service.SysRoleMenuRelationService;
import org.zpmis.domain.role.service.SysRolePermissionRelationService;
import org.zpmis.domain.role.vo.SysMenuListVo;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;

import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created with CodeGenerator
 * Description:
 * @author  Yang
 * Date: 2021-5-31
 * Time: 14:00:27
 */
@Service
@Slf4j
public class SysMenuWebService extends BaseWebService {
     @Reference
     private SysMenuService sysMenuService;

     @Reference
     private SysPermissionService sysPermissionService;

    @Reference
    private SysRoleMenuRelationService sysRoleMenuRelationService;

    @Reference
    private SysRolePermissionRelationService sysRolePermissionRelationService;

    /**
     * 新增菜单  同时新增对应的权限
     * @param addSysMenuQo
     * @throws BusinessException
     * @throws Exception
     */
    @Transactional
    public void addSysMenu(AddSysMenuQo addSysMenuQo) throws BusinessException,Exception {
        AdminLoginUser adminLoginUser = super.getAdminLoginUser();
        if(adminLoginUser == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        String menuKey = addSysMenuQo.getMenuKey();
        Map<String,Object> map = new HashMap<>();
        map.put("menuKey",menuKey);
        map.put("isDeleted",0);
        map.put("status",1);
        List<SysMenu> menuList = sysMenuService.findByConditionMap(map);
        if(menuList != null && !menuList.isEmpty()){
            throw new BusinessException(ResultCode.DATA_ALREADY_EXISTS);
        }
        //新增菜单
        sysMenuService.save(
        SysMenu.builder()
                .name(addSysMenuQo.getName())
                .parentMenuKey(addSysMenuQo.getParentMenuKey())
                .menuKey(addSysMenuQo.getMenuKey())
                .type(addSysMenuQo.getType())
                .menuCate(addSysMenuQo.getMenuCate())
                .icon(addSysMenuQo.getIcon())
                .sort(addSysMenuQo.getSort())
                .parentId(addSysMenuQo.getParentId()== null ? 0L : addSysMenuQo.getParentId())
                .routerUrl(addSysMenuQo.getRouterUrl())
                .menuGroup(addSysMenuQo.getMenuGroup())
                .isDeleted(0)
                .status(1)
                .createTime(Instant.now().toEpochMilli())
                .createUser(adminLoginUser.getId())
                .build()
        );
        if(StringUtil.isNotEmpty(addSysMenuQo.getRouterUrl())){
            //新增对应的权限
            sysPermissionService.save(
                    SysPermission.builder()
                            .apiUrl(addSysMenuQo.getRouterUrl())
                            .permissionGroup(addSysMenuQo.getMenuGroup())
                            .permissionName(addSysMenuQo.getName())
                            .createUser(adminLoginUser.getId())
                            .isDeleted(false)
                            .createTime(Instant.now().toEpochMilli())
                            .permissionCode("sys:permission:"+addSysMenuQo.getMenuGroup()+":"+ UUID.randomUUID().toString().replaceAll("-",""))
                            .build()
            );
        }

    }

    /**
     * 修改菜单
     * @param editSysMenuQo
     * @throws BusinessException
     * @throws Exception
     */
    @Transactional
    public void editSysMenu(EditSysMenuQo editSysMenuQo)  throws BusinessException,Exception {
        AdminLoginUser adminLoginUser = super.getAdminLoginUser();
        if(adminLoginUser == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        Long id = editSysMenuQo.getId();
        SysMenu sysMenu = sysMenuService.findById(id);
        if(sysMenu == null || sysMenu.getIsDeleted() == 1){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        String beforeUrl = sysMenu.getRouterUrl();
        sysMenu.setName(editSysMenuQo.getName());
        sysMenu.setParentMenuKey(editSysMenuQo.getParentMenuKey());
        sysMenu.setMenuKey(editSysMenuQo.getMenuKey());
        sysMenu.setType(editSysMenuQo.getType());
        sysMenu.setMenuCate(editSysMenuQo.getMenuCate());
        sysMenu.setIcon(editSysMenuQo.getIcon());
        sysMenu.setSort(editSysMenuQo.getSort());
        sysMenu.setParentId(editSysMenuQo.getParentId() == null ? 0L : editSysMenuQo.getParentId());
        sysMenu.setRouterUrl(editSysMenuQo.getRouterUrl());
        sysMenu.setStatus(editSysMenuQo.getStatus());
        sysMenu.setMenuGroup(editSysMenuQo.getMenuGroup());
        sysMenu.setUpdateTime(Instant.now().toEpochMilli());
        sysMenu.setUpdateUser(adminLoginUser.getId());
        sysMenuService.update(sysMenu);
        super.delLoginUserRedisDetail();
        if(StringUtil.isNotEmpty(editSysMenuQo.getRouterUrl()) && !editSysMenuQo.getRouterUrl().equals(beforeUrl)){
            //修改之前的权限
            Map<String,Object> param = new HashMap<>();
            param.put("apiUrl",beforeUrl);
            param.put("isDeleted",0);
            List<SysPermission> sysPermissionList = sysPermissionService.findByConditionMap(param);
            if(!sysPermissionList.isEmpty()){
                sysPermissionList.stream().forEach( sysPermission -> {
                    sysPermissionService.update(
                            SysPermission.builder()
                            .id(sysPermission.getId())
                            .apiUrl(editSysMenuQo.getRouterUrl())
                            .build()
                    );
                });
            }else{
                //新增对应的权限
                sysPermissionService.save(
                        SysPermission.builder()
                                .apiUrl(editSysMenuQo.getRouterUrl())
                                .permissionGroup(editSysMenuQo.getMenuGroup())
                                .permissionName(editSysMenuQo.getName())
                                .createUser(adminLoginUser.getId())
                                .isDeleted(false)
                                .createTime(Instant.now().toEpochMilli())
                                .permissionCode("sys:permission:"+editSysMenuQo.getMenuGroup()+":"+ UUID.randomUUID().toString().replaceAll("-",""))
                                .build()
                );
            }
        }
    }

    /**
     * 删除菜单
     * @param delSysMenuQo
     * @throws BusinessException
     * @throws Exception
     */
    @Transactional
    public void delSysMenu(DelSysMenuQo delSysMenuQo)  throws BusinessException,Exception{
        AdminLoginUser adminLoginUser = super.getAdminLoginUser();
        if(adminLoginUser == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        Long id = delSysMenuQo.getId();
        SysMenu sysMenu = sysMenuService.findById(id);
        if(sysMenu == null){
            throw new BusinessException(ResultCode.DATA_NOT_FOUND);
        }
        //校验是否有子节点
        Map<String,Object> map = new HashMap<>();
        map.put("parentId",id);
        map.put("isDeleted",0);
        map.put("status",1);
        List<SysMenu> sysMenuList = sysMenuService.findByConditionMap(map);
        if(!sysMenuList.isEmpty()){
            throw new BusinessException(ResultCode.DATA_ALREADY_CHILD_EXISTS);
        }
        //删除菜单
        sysMenuService.deleteById(id);
        super.delLoginUserRedisDetail();
        //删除与此菜单关联的关联数据
        Map<String,Object> relationMap = new HashMap<>();
        relationMap.put("menuId",id);
        List<SysRoleMenuRelation> sysRoleMenuRelationList = sysRoleMenuRelationService.findByConditionMap(relationMap);
        if(!sysRoleMenuRelationList.isEmpty()){
            String relationIds = sysRoleMenuRelationList.stream().map(x -> x.getId().toString()).collect(Collectors.joining(","));
            sysRoleMenuRelationService.deleteByIds(relationIds);
        }

        //删除之前的权限
        Map<String,Object> param = new HashMap<>();
        param.put("apiUrl",sysMenu.getRouterUrl());
        param.put("isDeleted",0);
        List<SysPermission> sysPermissionList = sysPermissionService.findByConditionMap(param);
        if(!sysPermissionList.isEmpty()){
            //删除权限
            String pIds = sysPermissionList.stream().map(x -> x.getId().toString()).collect(Collectors.joining(","));
            sysPermissionService.deleteByIds(pIds);
            //删除与此权限关联的 关联数据
            Condition condition = new Condition(SysRolePermissionRelation.class);
            condition.createCriteria()
                    .andIn("permissionId",sysPermissionList.stream().map(SysPermission::getId).collect(Collectors.toList()));
            List<SysRolePermissionRelation> relationList = sysRolePermissionRelationService.findByCondition(condition);
            if(!relationList.isEmpty()){
                //删除关联数据
                String pRelationIds = relationList.stream().map(x -> x.getId().toString()).collect(Collectors.joining(","));
                sysRolePermissionRelationService.deleteByIds(pRelationIds);
            }
        }

    }

    /**
     * 菜单列表树集合
     * @param sysMenuListQo
     * @return
     * @throws BusinessException
     * @throws Exception
     */
    public List<SysMenuListVo> sysMenuList(SysMenuListQo sysMenuListQo) throws BusinessException,Exception{
        //查询系统所有顶级菜单
        Condition parentCondition = new Condition(SysMenu.class);
        Example.Criteria criteria = parentCondition.createCriteria();
        criteria.andEqualTo("parentId",0)
                .andEqualTo("type",1)
                .andEqualTo("isDeleted",0)
                .andEqualTo("status",1);
        if(StringUtil.isNotEmpty(sysMenuListQo.getName())){
            criteria.andLike("name","%"+sysMenuListQo.getName()+"%");
        }
        if(StringUtil.isNotEmpty(sysMenuListQo.getMenuKey())){
            criteria.andLike("menuKey","%"+sysMenuListQo.getMenuKey()+"%");
        }
        parentCondition.orderBy("sort").asc();
        List<SysMenu> parentSysMenuList = sysMenuService.findByCondition(parentCondition);
        List<SysMenuListVo> parentMenuListVo = parentSysMenuList.stream().map(SysMenuListVo::new).collect(Collectors.toList());
        List<SysMenuListVo> resultMenuListVo = this.recursiveQueryMenu(parentMenuListVo);
        return resultMenuListVo;
    }

    /**
     * 递归循环查询菜单
     * @param parentMenuListVo
     * @return
     */
    private List<SysMenuListVo> recursiveQueryMenu(List<SysMenuListVo> parentMenuListVo){
        //循环顶级菜单 放入二级菜单
        //Map<String,Object> childParam = new HashMap<>();
        //childParam.put("type",1);
        //childParam.put("isDeleted",0);
        //childParam.put("status",1);

        parentMenuListVo.stream().forEach(sysMenuVo -> {
            Long nextParentId = sysMenuVo.getId();
            Long parentId = sysMenuVo.getParentId();
            if(nextParentId == parentId){
                //如果当前对象的 父id 等于本身的id 则证明数据有误，会造成死循环，所以这里判断以免造成死循环
                return ;
            }
            //childParam.put("parentId",sysMenuVo.getId());
            Condition parentCondition = new Condition(SysMenu.class);
            Example.Criteria criteria = parentCondition.createCriteria();
            criteria.andEqualTo("isDeleted",0);
            criteria.andEqualTo("status",1);
            criteria.andEqualTo("parentId",sysMenuVo.getId());
            parentCondition.orderBy("sort").asc();
            List<SysMenu> childMenuList = sysMenuService.findByCondition(parentCondition);
            if(!childMenuList.isEmpty()){
                List<SysMenuListVo> sysChildMenuListVoList = childMenuList.stream().map(SysMenuListVo::new).collect(Collectors.toList());
                //放入子菜单集合
                sysMenuVo.getChildList().addAll(sysChildMenuListVoList);
                this.recursiveQueryMenu(sysChildMenuListVoList);
            }

        });

        return parentMenuListVo;
    }


    /**
     * 查询系统所有顶级菜单
     * @return
     */
    public List<SysMenuListVo> sysMenuParentList() {
        //查询系统所有顶级菜单
        Map<String,Object> parentParam = new HashMap<>();
        parentParam.put("parentId",0);
        parentParam.put("type",1);
        parentParam.put("isDeleted",0);
        parentParam.put("status",1);
        List<SysMenu> parentSysMenuList = sysMenuService.findByConditionMap(parentParam);
        List<SysMenuListVo> resultList = parentSysMenuList.stream().map(SysMenuListVo::new).collect(Collectors.toList());
        return resultList;
    }

    /**
     * 获取登录用户的菜单列表
     * @return
     * @throws BusinessException
     * @throws Exception
     */
    public List getUserSysMenu() throws BusinessException,Exception{
        AdminLoginUser adminLoginUser = super.getAdminLoginUser();
        if(adminLoginUser == null){
            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
        }
        List<Object> sysMenuList = adminLoginUser.getSysMenuList();
        return sysMenuList;
    }
}
